using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Admin.NET.Application.Entity.Business;
using Admin.NET.Application.EventBus;
using Admin.NET.Core;
using Essensoft.Paylink.Alipay;
using Essensoft.Paylink.Alipay.Notify;
using Furion;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.EventBus;
using Furion.FriendlyException;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using SqlSugar;

namespace Admin.NET.Application.Service.AliPay;

/// <summary>
/// 支付宝通知服务
/// </summary>
[ApiDescriptionSettings(new string[] { "业务应用" }, Order = 100)]
public class AliPayNotifyService : IDynamicApiController, ITransient, IPrivateDependency
{
	private readonly UserManager _userManager;

	private readonly SqlSugarRepository<AliPayProvider> _rep;

	private readonly IAlipayNotifyClient _client;

	private AlipayOptions _options;

	private readonly SqlSugarRepository<RoomBalanceRecord> _balanceRep;

	private readonly RoomService _roomService;

	public AliPayNotifyService(UserManager userManager, SqlSugarRepository<AliPayProvider> rep, IAlipayNotifyClient client, SqlSugarRepository<RoomBalanceRecord> balanceRep, RoomService roomService)
	{
		_userManager = userManager;
		_rep = rep;
		_client = client;
		_balanceRep = balanceRep;
		_roomService = roomService;
		SetAlipayOptions();
	}

	private void SetAlipayOptions()
	{
		AliPayProvider data = _rep.AsQueryable().First();
		if (data == null)
		{
			throw Oops.Bah("该平台暂未开通支付宝支付，请线下缴费");
		}
		_options = new AlipayOptions
		{
			AppId = data.AppId,
			AlipayPublicKey = data.AlipayPublicKey,
			AppPrivateKey = data.AppPrivateKey,
			EncryptKey = data.EncryptKey
		};
	}

	/// <summary>
	/// 应用网关
	/// </summary>
	/// <returns></returns>
	[HttpPost("/alipaynotify/gateway")]
	[NonUnify]
	public async Task<IActionResult> Gateway()
	{
		try
		{
			HttpRequest Request = App.HttpContext.Request;
			switch (Request.Form["msg_method"].ToString())
			{
			case "alipay.fund.trans.order.changed":
				await _client.CertificateExecuteAsync<AlipayFundTransOrderChangedNotify>(Request, _options);
				return AlipayNotifyResult.Success;
			case "alipay.open.auth.appauth.cancelled":
				await _client.CertificateExecuteAsync<AlipayOpenAuthAppauthCancelledNotify>(Request, _options);
				return AlipayNotifyResult.Success;
			case "alipay.open.auth.userauth.cancelled":
				await _client.CertificateExecuteAsync<AlipayOpenAuthUserauthCancelledNotify>(Request, _options);
				return AlipayNotifyResult.Success;
			case "alipay.open.mini.version.audit.passed":
				await _client.CertificateExecuteAsync<AlipayOpenMiniVersionAuditPassedNotify>(Request, _options);
				return AlipayNotifyResult.Success;
			case "alipay.open.mini.version.audit.rejected":
				await _client.CertificateExecuteAsync<AlipayOpenMiniVersionAuditRejectedNotify>(Request, _options);
				return AlipayNotifyResult.Success;
			case "alipay.trade.refund.depositback.completed":
				await _client.CertificateExecuteAsync<AlipayTradeRefundDepositbackCompletedNotify>(Request, _options);
				return AlipayNotifyResult.Success;
			case "alipay.trade.settle.dishonoured":
				await _client.CertificateExecuteAsync<AlipayTradeSettleDishonouredNotify>(Request, _options);
				return AlipayNotifyResult.Success;
			case "alipay.trade.settle.fail":
				await _client.CertificateExecuteAsync<AlipayTradeSettleFailNotify>(Request, _options);
				return AlipayNotifyResult.Success;
			case "alipay.trade.settle.success":
				await _client.CertificateExecuteAsync<AlipayTradeSettleSuccessNotify>(Request, _options);
				return AlipayNotifyResult.Success;
			case "alipay.user.certify.open.notify.completed":
				await _client.CertificateExecuteAsync<AlipayUserCertifyOpenNotifyCompletedNotify>(Request, _options);
				return AlipayNotifyResult.Success;
			default:
				return AlipayNotifyResult.Failure;
			}
		}
		catch (AlipayException)
		{
			return AlipayNotifyResult.Failure;
		}
	}

	/// <summary>
	/// 扫码支付异步通知
	/// </summary>
	[HttpPost("/alipaynotify/precreate")]
	[NonUnify]
	public async Task<IActionResult> Precreate()
	{
		try
		{
			HttpRequest Request = App.HttpContext.Request;
			string tradeStatus = (await _client.CertificateExecuteAsync<AlipayTradePrecreateNotify>(Request, _options)).TradeStatus;
			string text = tradeStatus;
			string text2 = text;
			if (!(text2 == "WAIT_BUYER_PAY"))
			{
				if (text2 == "TRADE_SUCCESS")
				{
					return AlipayNotifyResult.Success;
				}
				return AlipayNotifyResult.Failure;
			}
			return AlipayNotifyResult.Success;
		}
		catch (AlipayException)
		{
			return AlipayNotifyResult.Failure;
		}
	}

	/// <summary>
	/// APP支付异步通知
	/// </summary>
	[HttpPost("/alipaynotify/apppay")]
	[NonUnify]
	public async Task<IActionResult> AppPay()
	{
		try
		{
			HttpRequest Request = App.HttpContext.Request;
			return (await _client.CertificateExecuteAsync<AlipayTradeAppPayNotify>(Request, _options)).TradeStatus switch
			{
				"TRADE_SUCCESS" => AlipayNotifyResult.Success, 
				"TRADE_CLOSED" => AlipayNotifyResult.Success, 
				"TRADE_FINISHED" => AlipayNotifyResult.Success, 
				_ => AlipayNotifyResult.Failure, 
			};
		}
		catch (AlipayException)
		{
			return AlipayNotifyResult.Failure;
		}
	}

	/// <summary>
	/// 电脑网站支付异步通知
	/// </summary>
	[HttpPost("/alipaynotify/pagepay")]
	[NonUnify]
	public async Task<IActionResult> PagePay()
	{
		try
		{
			HttpRequest Request = App.HttpContext.Request;
			return (await _client.CertificateExecuteAsync<AlipayTradePagePayNotify>(Request, _options)).TradeStatus switch
			{
				"TRADE_SUCCESS" => AlipayNotifyResult.Success, 
				"TRADE_CLOSED" => AlipayNotifyResult.Success, 
				"TRADE_FINISHED" => AlipayNotifyResult.Success, 
				_ => AlipayNotifyResult.Failure, 
			};
		}
		catch (AlipayException)
		{
			return AlipayNotifyResult.Failure;
		}
	}

	/// <summary>
	/// 手机网站支付异步通知
	/// </summary>
	[HttpPost("/alipaynotify/wappay")]
	[NonUnify]
	public async Task<IActionResult> WapPay()
	{
		try
		{
			HttpRequest Request = App.HttpContext.Request;
			return (await _client.CertificateExecuteAsync<AlipayTradeWapPayNotify>(Request, _options)).TradeStatus switch
			{
				"TRADE_SUCCESS" => AlipayNotifyResult.Success, 
				"TRADE_CLOSED" => AlipayNotifyResult.Success, 
				"TRADE_FINISHED" => AlipayNotifyResult.Success, 
				_ => AlipayNotifyResult.Failure, 
			};
		}
		catch (AlipayException)
		{
			return AlipayNotifyResult.Failure;
		}
	}

	/// <summary>
	/// 小程序支付异步通知
	/// </summary>
	[HttpPost("/alipaynotify/mppay")]
	[NonUnify]
	[AllowAnonymous]
	public async Task<IActionResult> MpPay()
	{
		try
		{
			HttpRequest Request = App.HttpContext.Request;
			AlipayTradePayNotify notify = await _client.CertificateExecuteAsync<AlipayTradePayNotify>(Request, _options);
			switch (notify.TradeStatus)
			{
			case "TRADE_SUCCESS":
				await PayNotify(notify);
				return AlipayNotifyResult.Success;
			case "TRADE_CLOSED":
				return AlipayNotifyResult.Success;
			case "TRADE_FINISHED":
				return AlipayNotifyResult.Success;
			default:
				return AlipayNotifyResult.Failure;
			}
		}
		catch (AlipayException)
		{
			return AlipayNotifyResult.Failure;
		}
	}

	private async Task PayNotify(AlipayTradePayNotify callbackResource)
	{
		long roomId = 0L;
		try
		{
			await _rep.Context.Ado.BeginTranAsync();
			await _balanceRep.Context.Ado.BeginTranAsync();
			PaymentRecord wechatPay = await (from u in _rep.Context.Queryable<PaymentRecord>()
				where u.OutTradeNo == callbackResource.OutTradeNo && u.SubAppId == callbackResource.AuthAppId
				select u).FirstAsync();
			if (wechatPay == null || wechatPay.IsPay != 0)
			{
				return;
			}
			roomId = wechatPay.RoomId.Value;
			wechatPay.TradeNo = callbackResource.TradeNo;
			wechatPay.TradeStatus = callbackResource.TradeStatus;
			wechatPay.BuyerPayAmount = callbackResource.BuyerPayAmount;
			wechatPay.SuccessTime = DateTime.Parse(callbackResource.NotifyTime);
			wechatPay.NotifyTime = DateTime.Now;
			wechatPay.IsPay = 1;
			if (!string.IsNullOrWhiteSpace(callbackResource.ReceiptAmount))
			{
				wechatPay.ReceiptAmount = decimal.Parse(callbackResource.ReceiptAmount);
			}
			await _rep.Context.Updateable(wechatPay).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync();
			decimal amount = wechatPay.Amount - wechatPay.Rate;
			if (wechatPay.IsCustomBill.GetValueOrDefault() == 1)
			{
				IUpdateable<CustomRoomBill> tmp = _rep.Context.Updateable<CustomRoomBill>();
				tmp = tmp.SetColumns((CustomRoomBill s) => s.Status == 2);
				await tmp.Where((CustomRoomBill s) => (long?)s.Id == wechatPay.CustomRoomBillId).ExecuteCommandAsync();
			}
			else
			{
				IUpdateable<Room> tmp = _rep.Context.Updateable<Room>();
				tmp = tmp.SetColumns((Room s) => new Room
				{
					Balance = s.Balance + amount
				});
				await tmp.Where((Room s) => (long?)s.Id == wechatPay.RoomId).ExecuteCommandAsync();
				await _roomService.AddRoomBalanceRecord(_balanceRep.Context, wechatPay.RoomId.Value, wechatPay.Id, 0, wechatPay.Amount, wechatPay.TenantId.Value, "微信充值");
			}
			try
			{
				Room roomInfo = await (from w in _rep.Context.Queryable<Room>()
					where w.Id == roomId && w.TenantId == wechatPay.TenantId
					select w).FirstAsync();
				if (roomInfo != null && roomInfo.OwnerId.HasValue)
				{
					Owner owner = await (from w in _rep.Context.Queryable<Owner>()
						where (long?)w.Id == roomInfo.OwnerId && w.TenantId == wechatPay.TenantId
						select w).FirstAsync();
					if (owner != null)
					{
						BillNoticePayload billNoticePayload = new BillNoticePayload
						{
							Body = $"您的房间：{roomInfo.Name}缴费成功，金额{wechatPay.Amount}元，到账{amount}元",
							Subject = "缴费成功提醒",
							Owners = new List<Owner> { owner },
							RoomId = roomInfo.Id,
							RoomName = roomInfo.Name,
							OrderNo = wechatPay.OutTradeNo,
							Amount = wechatPay.Amount.ToString(),
							Path = "/userPage/roomDetail/roomDetail?roomId=" + roomInfo.Id
						};
						EventPayload payload = new EventPayload
						{
							Data = JsonConvert.SerializeObject(billNoticePayload),
							TenantId = roomInfo.TenantId.Value
						};
						for (int i = 0; i < 4; i++)
						{
							MessageCenter.PublishAsync($"{i}:SendPaymentNotice", payload).Wait();
						}
					}
				}
			}
			catch (Exception)
			{
			}
			await _rep.Context.Ado.CommitTranAsync();
			await _balanceRep.Context.Ado.CommitTranAsync();
			try
			{
				EventPayload payload2 = new EventPayload
				{
					Data = roomId.ToString(),
					TenantId = wechatPay.TenantId.Value
				};
				await MessageCenter.PublishAsync("SwitchOnGate", payload2);
			}
			catch (Exception)
			{
			}
		}
		catch (Exception ex)
		{
			await _rep.Context.Ado.RollbackTranAsync();
			await _balanceRep.Context.Ado.RollbackTranAsync();
			throw ex;
		}
	}

	/// <summary>
	/// 交易关闭异步通知
	/// </summary>
	[HttpPost("/alipaynotify/close")]
	[NonUnify]
	public async Task<IActionResult> Close()
	{
		try
		{
			HttpRequest Request = App.HttpContext.Request;
			if ((await _client.CertificateExecuteAsync<AlipayTradeCloseNotify>(Request, _options)).TradeStatus == "TRADE_CLOSED")
			{
				return AlipayNotifyResult.Success;
			}
			return AlipayNotifyResult.Failure;
		}
		catch (AlipayException)
		{
			return AlipayNotifyResult.Failure;
		}
	}
}
